package cn.gailvlun.gll.chatkit.message

import android.Manifest
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.graphics.Rect
import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.GridLayoutManager
import android.support.v7.widget.RecyclerView
import android.text.InputFilter
import android.util.AttributeSet
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.widget.EditText
import android.widget.ImageButton
import android.widget.LinearLayout
import android.widget.TextView
import cn.gailvlun.gll.chatkit.R
import cn.gailvlun.gll.chatkit.StickerLayoutManager
import cn.gailvlun.gll.chatkit.record.IRecordView
import cn.gailvlun.gll.chatkit.record.RecordButton
import cn.gailvlun.gll.chatkit.sticker.CategoryAdapter
import cn.gailvlun.gll.chatkit.sticker.StickerAdapter
import cn.gailvlun.gll.chatkit.sticker.StickerPageChangeListener
import cn.gailvlun.gll.chatkit.sticker.StickerSnapHelper
import cn.gailvlun.gll.util.DensityUtil
import cn.gailvlun.gll.util.StringUtil
import cn.gailvlun.gll.util.ToastUtil
import cn.gailvlun.gll.widget.edittext.BaseFilter
import com.blankj.utilcode.util.FileUtils
import com.blankj.utilcode.util.KeyboardUtils
import com.github.markzhai.recyclerview.BaseViewAdapter
import com.jakewharton.rxbinding2.view.RxView
import com.jakewharton.rxbinding2.widget.RxTextView
import com.luck.picture.lib.PictureSelector
import com.luck.picture.lib.PictureSelectorActivity
import com.luck.picture.lib.config.PictureConfig
import com.luck.picture.lib.config.PictureMimeType
import com.luck.picture.lib.permissions.RxPermissions
import com.vanniktech.emoji.EmojiEditText
import io.reactivex.Observable
import kotlinx.android.synthetic.main.message_input.view.*
import kotlinx.android.synthetic.main.tab_sticker.view.*
import rx_activity_result2.RxActivityResult
import java.io.File
import java.util.*


class MessageInput : LinearLayout {

    val mEmojiList = arrayOf("😄", "😃", "😀", "😊", "☺", "😉", "😍", "😘", "😚", "😗", "😙", "😜", "😝", "😛", "😳", "😁", "😔", "😌", "😒", "😞", "😣", "😢", "😂", "😭", "😪", "😥", "😰", "😅", "😓", "😩", "😫", "😨", "😱", "😠", "😡", "😤", "😖", "😆", "😋", "😷", "😎", "😴", "😵", "😲", "😟", "😦", "😧", "😈", "👿", "😮", "😬", "😐", "😕", "😯", "😶", "😇", "😏", "😑", "👲", "👳", "👮", "👷", "💂", "👶", "👦", "👧", "👨", "👩", "👴", "👵", "👱", "👼", "👸", "😺", "😸", "😻", "😽", "😼", "🙀", "😿")

    constructor(context: Context?) : this(context, null)
    constructor(context: Context?, attrs: AttributeSet?) : this(context, attrs, 0)
    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
        mContext = context as AppCompatActivity

        init(context)


        vp_category.adapter = CategoryAdapter(mContext.supportFragmentManager, titles.size)


        stl_category.setCustomTabView { container, position, _ ->
            if (position == 0) {
                LayoutInflater.from(container.context).inflate(R.layout.tab_sticker_emoji, container, false)
            } else {
                LayoutInflater.from(container.context).inflate(R.layout.tab_sticker, container, false).apply {
                    tv_tab_sticker.text = titles[position]
                }
            }
        }
        stl_category.setViewPager(vp_category)


        stl_category.setOnTabClickListener {

            var page = 0
            if (it > 0) {
                page += pages.asList().subList(0, it).reduce { a, b ->
                    a + b
                }
            }


            (mLayoutManager as StickerLayoutManager).scrollToPage(page)

            pcv.setCount(getCurrentCountBy(page))
            pcv.setCurrentPosition(getCurrentPosBy(page))
        }


        recycler_view.setHasFixedSize(true)
        mAdapter = StickerAdapter(mContext)
        mAdapter?.setPresenter(Presenter())
        recycler_view.adapter = mAdapter

        mLayoutManager = StickerLayoutManager(7, 3, 80, 5, 2)
        recycler_view.layoutManager = mLayoutManager

        val snapHelper = StickerSnapHelper(7, 3, 80, 5, 2)
        snapHelper.attachToRecyclerView(recycler_view)


        createHandler()
        loadData()


        snapHelper.mStickerPageChangeListener = object : StickerPageChangeListener {
            override fun onStickerPageChangeListener(page: Int) {
                pcv.setCount(getCurrentCountBy(page))
                pcv.setCurrentPosition(getCurrentPosBy(page))


                vp_category.currentItem = getTabBy(page)
            }
        }


        pcv.setCount(getCurrentCountBy(0))
        pcv.setCurrentPosition(getCurrentPosBy(0))
    }

    private var mState = State.INPUT

    private var mType = Type.MEMBER

    private val mContext: AppCompatActivity

    private var ibVoice: ImageButton? = null
    private var ibKeyboard: ImageButton? = null
    private var etInput: EmojiEditText? = null
    private var rbVoice: RecordButton? = null
    private var ibEmoji: ImageButton? = null
    private var ibMore: ImageButton? = null
    private var tvSend: TextView? = null

    private var llEmoji: View? = null
    private var llMore: View? = null
    private var rvMore: RecyclerView? = null
    private var moreAdapter: MoreAdapter? = null
    private var moreLayoutManager: GridLayoutManager? = null

    private var mMoreViewModels: MutableList<MoreViewModel>? = null

    private var restoreCache = false

    private var titles: Array<String> = arrayOf("emoji", "你好呀", "再见咯", "卖个萌", "吐个槽", "不开心", "尴尬了")
    private var dirNames: Array<String> = arrayOf("emoji", "hello", "bye", "cute", "complaints", "not_happy", "awkward")
    private var sizes: IntArray = intArrayOf(80, 30, 30, 30, 30, 30, 30)

    private var mAdapter: StickerAdapter? = null
    private var mLayoutManager: RecyclerView.LayoutManager? = null

    private lateinit var pages: IntArray

    val cache: String?
        get() {
            val editingText = etInput!!.text.toString()
            return if (!StringUtil.isAllSpace(editingText)) editingText else null
        }


    private

    val isSoftShowing: Boolean
        get() {
            val SOFT_KEYBOARD_HEIGHT_DP_THRESHOLD = 128
            val screenHeight = mContext.window.decorView.height
            val rect = Rect()
            mContext.window.decorView.getWindowVisibleDisplayFrame(rect)

            return Math.abs(screenHeight - rect.bottom) > DensityUtil.dp2px(mContext,
                    SOFT_KEYBOARD_HEIGHT_DP_THRESHOLD.toFloat())
        }

    private var mOnSubmitListener: OnSubmitListener? = null
    private var mOnPictureSuccessListener: OnPictureSuccessListener? = null
    private var mOnReviewCheckListener: OnReviewCheckListener? = null

    private var mOnAtSignListener: OnAtSignListener? = null
    private var mOnCheckCpListener: OnCheckCpListener? = null

    private enum class State {
        INPUT, VOICE
    }

    enum class Type {
        MEMBER, HOST
    }

    private fun init(context: Context) {
        View.inflate(context, R.layout.message_input, this)

        ibVoice = findViewById(R.id.ib_voice)
        ibKeyboard = findViewById(R.id.ib_keyboard)
        etInput = findViewById(R.id.et_input)
        rbVoice = findViewById(R.id.tv_voice)
        ibEmoji = findViewById(R.id.ib_emoji)
        ibMore = findViewById(R.id.ib_more)
        tvSend = findViewById(R.id.tv_send)

        llEmoji = findViewById(R.id.ll_emoji)
        llMore = findViewById(R.id.ll_more)
        rvMore = findViewById(R.id.rv_more)

        moreAdapter = MoreAdapter(mContext)
        moreAdapter!!.setPresenter(Presenter())
        rvMore!!.adapter = moreAdapter

        moreLayoutManager = GridLayoutManager(mContext, 4)
        rvMore!!.layoutManager = moreLayoutManager
    }

    private fun createHandler() {
        Observable.merge(RxView.clicks(ibVoice!!), RxView.clicks(ibKeyboard!!))
                .subscribe { toggleVoice() }


        RxTextView.textChanges(etInput!!)
                .subscribe { charSequence ->
                    if (charSequence.length > 0) {
                        if (ibMore!!.visibility == View.VISIBLE) {
                            ibMore!!.visibility = View.INVISIBLE
                        }
                        if (tvSend!!.visibility != View.VISIBLE) {
                            tvSend!!.visibility = View.VISIBLE
                        }
                    } else {
                        if (ibMore!!.visibility != View.VISIBLE) {
                            ibMore!!.visibility = View.VISIBLE
                        }
                        if (tvSend!!.visibility == View.VISIBLE) {
                            tvSend!!.visibility = View.INVISIBLE
                        }
                    }
                }

        etInput!!.filters = arrayOf<InputFilter>(object : BaseFilter() {
            override fun isAllowed(c: Char): Boolean {
                if (mOnAtSignListener != null && !restoreCache && c == '@') {
                    mOnAtSignListener!!.onAtSign()
                }
                return true
            }
        })

        RxView.clicks(ibEmoji!!)
                .subscribe {
                    if (mState == State.VOICE) {
                        toggleVoice()
                        llEmoji!!.visibility = View.VISIBLE
                    } else {
                        KeyboardUtils.hideSoftInput(etInput)
                        if (llEmoji!!.visibility == View.VISIBLE) {
                            llEmoji!!.visibility = View.GONE
                        } else {
                            llEmoji?.visibility = View.VISIBLE
                        }
                        llMore!!.visibility = View.GONE
                    }
                }

        RxView.clicks(ibMore!!)
                .subscribe { toggleMore() }

        RxView.clicks(tvSend!!)
                .subscribe {
                    if (mOnSubmitListener != null) {
                        mOnSubmitListener!!.onSubmit(etInput!!)
                    }
                }

        RxView.clicks(etInput!!)
                .subscribe {
                    setState(State.INPUT)


                }
        RxView.focusChanges(etInput!!)
                .subscribe { aBoolean ->
                    if (aBoolean!!) {
                        restoreCache = false
                        setState(State.INPUT)
                    }
                }
    }

    private val stickerRootDirName = "sticker"

    var stickerListList = ArrayList<ArrayList<String>>()

    fun loadData() {

        val names = resources.getStringArray(R.array.message_input_more_name)
        val ta = resources.obtainTypedArray(R.array.message_input_more_icon)

        mMoreViewModels = ArrayList()
        for (i in names.indices) {
            val moreViewModel = MoreViewModel()
            moreViewModel.order = i

            moreViewModel.icon = ta.getResourceId(i, R.drawable.ic_placeholder_square)
            moreViewModel.name = names[i]
            mMoreViewModels!!.add(moreViewModel)
        }

        ta.recycle()
        setType(mType)


//        var emojiArray = mContext.resources.getStringArray(R.array.emoji_array)
        val emojiList = ArrayList<String>()
        mEmojiList.forEach {
            emojiList.add(it)
        }
        stickerListList.add(emojiList)

        dirNames.forEachIndexed { index, dirName ->
            if (index != 0) {
                val stickerList = ArrayList<String>()
                for (stickerIndex in 0 until sizes[index]) {
                    stickerList.add("file:///android_asset/$stickerRootDirName/$dirName/ic_$dirName$stickerIndex.jpg")
                }
                stickerListList.add(stickerList)
            }
        }

        sizes = IntArray(stickerListList.size) {
            return@IntArray stickerListList[it].size
        }

        pages = IntArray(sizes.size) {
            if (it == 0) {
                val i = sizes[it]
                if (i % 21 != 0) {
                    i / 21 + 1
                } else {
                    i / 21
                }
            } else {
                val i = sizes[it]
                if (i % 10 != 0) {
                    i / 10 + 1
                } else {
                    i / 10
                }
            }
        }


        mAdapter?.addAllSticker(stickerListList)
    }

    fun setType(type: Type) {
        mType = type
        var permissions = resources.getIntArray(R.array.message_input_role_normal)
        when (type) {
            MessageInput.Type.MEMBER -> {
                permissions = resources.getIntArray(R.array.message_input_role_normal)
            }
            MessageInput.Type.HOST -> {
                permissions = resources.getIntArray(R.array.message_input_role_host)
            }
        }
        val permissionList = ArrayList<Int>()
        for (permission in permissions) {
            permissionList.add(permission)
        }
        for (i in mMoreViewModels!!.indices.reversed()) {
            mMoreViewModels!![i].isVisible = permissionList.contains(i)
        }
        moreAdapter!!.set(mMoreViewModels)
    }

    private fun setState(state: State) {
        mState = state
        when (state) {
            MessageInput.State.INPUT -> {
                llEmoji!!.visibility = View.GONE
                llMore!!.visibility = View.GONE
            }
            MessageInput.State.VOICE -> {
                llEmoji!!.visibility = View.GONE
                llEmoji!!.visibility = View.GONE
                if (isSoftShowing) {
                    KeyboardUtils.hideSoftInput(etInput)
                }
            }
        }
    }

    fun hideMore() {
        if (llMore!!.visibility == View.VISIBLE) {
            llMore!!.visibility = View.GONE
        }
    }

    private fun toggleMore() {
        if (isSoftShowing) {
            KeyboardUtils.hideSoftInput(etInput)
        }
        if (llEmoji?.visibility == View.VISIBLE) {
            llEmoji?.visibility = View.GONE
        }
        if (llMore!!.visibility == View.VISIBLE) {
            llMore!!.visibility = View.GONE
        } else {
            llMore!!.visibility = View.VISIBLE
        }
    }

    private fun toggleVoice() {
        if (mState == State.INPUT) {
            if (!rbVoice!!.isHasPermission) {
                RxPermissions(mContext)
                        .request(Manifest.permission.RECORD_AUDIO,
                                Manifest.permission.WRITE_EXTERNAL_STORAGE)
                        .subscribe { aBoolean ->
                            if (aBoolean!!) {
                                rbVoice!!.isHasPermission = true
                            } else {
                                rbVoice!!.isHasPermission = false
                                ToastUtil.showShort("没有录音权限")
                            }
                        }
            }

            setState(State.VOICE)
            ibVoice!!.visibility = View.INVISIBLE
            ibKeyboard!!.visibility = View.VISIBLE
            etInput!!.visibility = View.INVISIBLE
            rbVoice!!.visibility = View.VISIBLE

            ibMore!!.visibility = View.VISIBLE
            tvSend!!.visibility = View.INVISIBLE
        } else if (mState == State.VOICE) {
            setState(State.INPUT)
            ibVoice!!.visibility = View.VISIBLE
            ibKeyboard!!.visibility = View.INVISIBLE
            etInput!!.visibility = View.VISIBLE
            rbVoice!!.visibility = View.INVISIBLE

            if (etInput!!.text.isNotEmpty()) {
                ibMore!!.visibility = View.INVISIBLE
                tvSend!!.visibility = View.VISIBLE
            }


            etInput!!.requestFocus()
        }
    }

    fun setRecordView(recordView: IRecordView) {
        if (rbVoice != null) {
            rbVoice!!.setRecordView(recordView)
        }
    }

    fun restoreCache(cache: String) {
        restoreCache = true
        etInput!!.setText(cache)
    }

    fun appendText(text: String) {
        val index = etInput!!.selectionStart
        val edit = etInput!!.editableText
        if (index < 0 || index >= edit.length) {
            edit.append(text)
        } else {
            edit.insert(index, text)
        }
    }

    var mOnClickEmojiListener: OnClickEmojiListener? = null
    var mOnClickStickerListener: OnClickStickerListener? = null

    inner class Presenter : BaseViewAdapter.Presenter {
        fun onClickMore(item: MoreViewModel) {
            when (item.order) {
                0 -> {
                    PictureSelector.create(mContext)
                            .openGallery(PictureMimeType.ofImage())
                            .maxSelectNum(1)
                            .minSelectNum(1)
                            .imageSpanCount(4)
                            .selectionMode(PictureConfig.SINGLE)
                            .previewImage(true)
                            .isCamera(true)
                            .imageFormat(PictureMimeType.PNG)
                            .isZoomAnim(true)
                            .sizeMultiplier(0.5f)
                            .setOutputCameraPath("/camera")
                            .previewEggs(true)
                            .compress(true)
                            .cropCompressQuality(50)
                            .minimumCompressSize(200)

                    RxActivityResult.on(mContext)
                            .startIntent(Intent(mContext, PictureSelectorActivity::class.java))
                            .subscribe { activityResult ->
                                if (activityResult.resultCode() == Activity.RESULT_OK && mOnPictureSuccessListener != null) {
                                    val list = PictureSelector.obtainMultipleResult(activityResult.data())
                                    val localMedia = list[0]
                                    val usefulPath: String
                                    usefulPath = if (localMedia.compressPath != null) {
                                        localMedia.compressPath
                                    } else {
                                        localMedia.path
                                    }
                                    mOnPictureSuccessListener!!.onPictureSuccess(FileUtils.getFileByPath(usefulPath),
                                            localMedia.width, localMedia.height)
                                }
                            }
                }
                1 -> {
                    PictureSelector.create(mContext)
                            .openCamera(PictureMimeType.ofImage())

                            .maxSelectNum(1)
                            .minSelectNum(1)
                            .imageSpanCount(4)
                            .selectionMode(PictureConfig.SINGLE)
                            .previewImage(true)
                            .isCamera(true)
                            .imageFormat(PictureMimeType.PNG)
                            .isZoomAnim(true)
                            .sizeMultiplier(0.5f)
                            .setOutputCameraPath("/camera")
                            .previewEggs(true)
                            .compress(true)
                            .cropCompressQuality(50)
                            .minimumCompressSize(200)

                    RxActivityResult.on(mContext)
                            .startIntent(Intent(mContext, PictureSelectorActivity::class.java))
                            .subscribe { activityResult ->
                                if (activityResult.resultCode() == Activity.RESULT_OK && mOnPictureSuccessListener != null) {
                                    val list = PictureSelector.obtainMultipleResult(activityResult.data())
                                    val localMedia = list[0]
                                    val usefulPath: String
                                    usefulPath = if (localMedia.compressPath != null) {
                                        localMedia.compressPath
                                    } else {
                                        localMedia.path
                                    }
                                    mOnPictureSuccessListener!!.onPictureSuccess(FileUtils.getFileByPath(usefulPath),
                                            localMedia.width, localMedia.height)
                                }
                            }
                }


                2 -> {
                    if (mOnReviewCheckListener != null) {
                        mOnReviewCheckListener!!.onReviewCheckClick()
                    }
                }
                3 -> {
                    if (mOnCheckCpListener != null) {
                        mOnCheckCpListener!!.onCheckCp()
                    }
                }
            }


        }

        fun onClickEmoji(emoji: String) {
            mOnClickEmojiListener?.onClickEmoji(etInput!!, emoji)
        }

        fun onClickSticker(stickerPath: String) {
            mOnClickStickerListener?.onClickSticker(stickerPath)
        }
    }

    private fun getCurrentCountBy(page: Int): Int {
        var leftPage = page
        for (i in 0 until pages.size) {
            if (leftPage - pages[i] < 0) {
                return pages[i]
            }
            leftPage -= pages[i]
        }
        return pages[0]
    }

    private fun getCurrentPosBy(page: Int): Int {
        var leftPage = page
        for (i in 0 until pages.size) {
            if (leftPage - pages[i] < 0) {
                break
            }
            leftPage -= pages[i]
        }
        return leftPage
    }

    private fun getTabBy(page: Int): Int {
        var leftPage = page
        for (i in 0 until pages.size) {
            if (leftPage - pages[i] < 0) {
                return i
            }
            leftPage -= pages[i]
        }
        return 0
    }

    interface OnSubmitListener {
        fun onSubmit(etInput: EditText)
    }

    interface OnPictureSuccessListener {
        fun onPictureSuccess(pictureFile: File, width: Int, height: Int)
    }

    interface OnReviewCheckListener {
        fun onReviewCheckClick()
    }

    fun setOnSubmitListener(onSubmitListener: OnSubmitListener) {
        this.mOnSubmitListener = onSubmitListener
    }

    fun setOnVoiceSuccessListener(onVoiceSuccessListener: OnVoiceSuccessListener) {
        rbVoice!!.setOnVoiceSuccessListener(onVoiceSuccessListener)
    }

    fun setOnPictureSuccessListener(onPictureSuccessListener: OnPictureSuccessListener) {
        this.mOnPictureSuccessListener = onPictureSuccessListener
    }

    fun setOnReviewCheckListener(onReviewCheckListener: OnReviewCheckListener) {
        this.mOnReviewCheckListener = onReviewCheckListener
    }

    interface OnAtSignListener {
        fun onAtSign()
    }

    fun setOnAtSignListener(onAtSignListener: OnAtSignListener) {
        this.mOnAtSignListener = onAtSignListener
    }

    interface OnCheckCpListener {
        fun onCheckCp()
    }

    fun setOnCheckCpListener(onCheckCpListener: OnCheckCpListener) {
        mOnCheckCpListener = onCheckCpListener
    }
}

interface OnClickEmojiListener {
    fun onClickEmoji(editText: EditText, emoji: String)
}

interface OnClickStickerListener {
    fun onClickSticker(stickerLocalPath: String)
}